package com.coin900.coin.server.fu.ctrl;

import com.coin900.coin.base.AjaxResponse;
import com.coin900.coin.base.BxConstants;
import com.coin900.coin.base.FuConstants;
import com.coin900.coin.base.enums.ResponseEnum;
import com.coin900.coin.persist.fu.BxUserIdDocumentV0;
import com.coin900.coin.persist.fu.BxUserInfoVO;
import com.coin900.coin.persist.fu.FuUserAuthVO;
import com.coin900.coin.persist.fu.FuUserVO;
import com.coin900.coin.server.BaseController;
import com.coin900.coin.server.fu.form.BxLoginForm;
import com.coin900.coin.server.fu.form.LoginForm;
import com.coin900.coin.service.fu.IFuUserService;
import com.google.gson.Gson;
import com.value.mybatis.DaoRouter;
import com.value.utils.Md5Encoder;
import net.sf.json.JSONObject;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.session.SqlSession;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author shui
 * @create 2017-11-21
 **/
@Controller
public class SessionCtrl extends BaseController {

    private static final Log logger = LogFactory.getLog(BaseController.class);

    @RequestMapping(value = "/tologin", method = RequestMethod.GET)
    public ModelAndView toLogin(String viewType,
                                HttpServletRequest request) {

        if (FuConstants.FU_PAGE.equals(viewType)) {
            ModelAndView modelAndView = super.buildView(request, "project/login");
            return modelAndView;
        }
        return null;
    }


    /**
     * 登录
     *
     * @param loginForm
     * @param br
     * @param loginType 1 tokenok 2coin900
     * @param request
     * @return
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public Object login(@Valid @RequestBody LoginForm loginForm,
                        BindingResult br,
                        @RequestParam String loginType,
                        HttpServletRequest request) {
        AjaxResponse response = super.buildAjaxResponse(request);
        //服务器端验证
        if (br.hasErrors()) {
            response.addError(br);
            return response.getMav();
        }
        String email = loginForm.getEmail();
        String password = loginForm.getPassword();
        Subject currentUser = SecurityUtils.getSubject();
        if (getUser() != null) {
            currentUser.logout();
        }

        FuUserVO user = null;

        if (loginType.equals(String.valueOf(FuConstants.FU_USER_TYPE_TOKENOK))) {
            // 众投账号登录
            Map<String, Object> params = new HashMap<>();
            params.put("loginUsername", email);
            params.put("password", Md5Encoder.generateCode(password));
            params.put("userType", FuConstants.FU_USER_TYPE_TOKENOK);
            params.put("dataStatus", 1);
            List<FuUserVO> userVOList = this.userService.loadFuUser(params);
            if (userVOList.isEmpty()) {
                response.addError("username", "Fail.Session.Auth");
                response.setStat(ResponseEnum.AUTHC_FAIL);
                return response.getMav();
            }
            user = userVOList.get(0);
        } else if (loginType.equals(String.valueOf(FuConstants.FU_USER_TYPE_COIN900))) {

            /**
             * 调用币新登录接口进行登录
             *
             * 登录成功
             * 判断用户表中是否存在该用户
             * 用户存在，表示已经拉取过实名信息，直接登录
             * 不存在，在用户表中新建一个默认密码的新用户，同时拉取用户的实名认证信息
             *
             * 登录失败
             * 返回登录失败的信息
             */

            BxLoginForm bxLoginForm = new BxLoginForm();
            bxLoginForm.setClient_id(BxConstants.BX_CLIENT_ID);
            bxLoginForm.setClient_secret(BxConstants.BX_CLIENT_SECRET);
            bxLoginForm.setEmail(email);
            bxLoginForm.setPassword(password);
            bxLoginForm.setGrant_type(BxConstants.BX_GRANT_TYPE);
            // 发起一个币新的登录请求，获取返回数据
            RestTemplate restTemplate = new RestTemplate();
            HttpEntity<BxLoginForm> req = new HttpEntity<>(bxLoginForm);
            ResponseEntity<String> resp = restTemplate.exchange(BxConstants.BX_PREFIX + BxConstants.BX_LOGIN, HttpMethod.POST, req, String.class);
            String body = resp.getBody();
            HttpStatus statusCode = resp.getStatusCode();
            if (statusCode.equals(HttpStatus.OK)) {
                // 币新账号登录成功
                JSONObject jsonObject = JSONObject.fromObject(body);
                String asscssToken = jsonObject.getString("access_token");

                // 判断用户是否在 TokenOk 注册
                // 币新登录的用户都用统一的默认密码
                password = Md5Encoder.generateCode(BxConstants.BX_DEFAULT_PASSWORD);
                Map<String, Object> params = new HashMap<>();
                params.put("loginUsername", email);
                params.put("password", password);
                params.put("userType", FuConstants.FU_USER_TYPE_COIN900);
                List<FuUserVO> userVOList = this.userService.loadFuUser(params);
                if (userVOList.isEmpty()) {
                    // 未在 TokenOk 注册，则注册成为 TokenOk 用户，并且从币新获取用户实名认证信息，设置默认密码
                    // 获取用户认证信息
                    String token = asscssToken.split(":")[0];
                    req = new HttpEntity<>(
                            new HttpHeaders() {
                                {
                                    String authHeader = "Token token=" + token;
                                    set("Authorization", authHeader);

                                }

                            }
                    );
                    resp = restTemplate.exchange(BxConstants.BX_PREFIX + BxConstants.BX_MY_QUERY, HttpMethod.GET, req, String.class);
                    body = resp.getBody();
                    jsonObject = JSONObject.fromObject(body);
                    BxUserInfoVO bxUserInfoVO = new Gson().fromJson(jsonObject.getString("data").toString(), BxUserInfoVO.class);
                    BxUserIdDocumentV0 idDocumentV0 = bxUserInfoVO.getId_document();
                    String state = idDocumentV0.getState();
                    FuUserVO userVO = new FuUserVO();
                    if (BxConstants.BX_ID_DOCUMENT_STATUS.equals(state)) {
                        // 认证状态为激活
                        userVO.setIdcardStatus(1);
                        FuUserAuthVO fuUserAuthVO = new FuUserAuthVO();
                        fuUserAuthVO.setName(idDocumentV0.getName());
                        fuUserAuthVO.setIdNo(idDocumentV0.getId_document_number());
                        userVO.setUserAuthVO(fuUserAuthVO);
                    }
                    // 用户名默认为邮箱
                    userVO.setUsername(email);
                    userVO.setEmail(email);
                    userVO.setPassword(password);
                    userVO.setCreatedBy(0L);
                    userVO.setCreatedDate(new Date());
                    // 邮箱状态为激活
                    userVO.setEmailStatus(1);
                    this.userService.insertFuUserByBxLogin(userVO);
                    user = userVO;
                } else {
                    user = userVOList.get(0);
                }
            }else {
                // 状态码不是 200，登录失败
                response.addError("username", "Fail.Session.Auth");
                response.setStat(ResponseEnum.AUTHC_FAIL);
                return response.getMav();
            }
        }

        email = user.getEmail();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(email, password);
        usernamePasswordToken.setRememberMe(true);
        try {
            currentUser.login(usernamePasswordToken);
        } catch (AuthenticationException e) {
            e.printStackTrace();
            response.addError("username", "Fail.Session.Auth");
            response.setStat(ResponseEnum.AUTHC_FAIL);
            return response.getMav();
        }
        Session session = currentUser.getSession();
        session.setAttribute("user", user);

        return response.getMav();
    }


    /**
     * 用户登出
     */
    @RequestMapping(value = "/logout", method = RequestMethod.DELETE)
    public ModelAndView logout(HttpServletRequest request) {
        AjaxResponse resp = super.buildAjaxResponse(request);
        SecurityUtils.getSubject().logout();
        return resp.getMav();
    }


    @Autowired
    private IFuUserService userService;
    @Autowired
    private DaoRouter daoRouter;
    @Autowired
    private SqlSession sqlSession;
}
